import React, { SyntheticEvent, createRef, useContext, useEffect, useRef, useState } from "react";
import { Button, Container, Form, Image, InputGroup, ListGroup, Offcanvas } from "react-bootstrap";
import ChatHelper from '../../../helper/chat/Chathelper';
import "./index.css"
import ChatMessage, { ChatMessageKind, ChatMessageSenderReceiverType } from "../../../helper/chat/ChatMessage";
import utils from "../../../utils";
import moment from "moment";
import { useLocation } from "react-router-dom";
import { toast } from "react-toastify";
import { PageHelper } from "../../../helper";
import ChatService from "../../../services/chatservice";
import { PopupDialog } from "../../../components/common";
import ChatDialogContactList from "./ChatDialogContactList";
import AuthenticationContext from "../../../context/Context";
import eventEmitter from "../../../utils/EventEmitter";
import constants from "../../../constants";

interface ChatDialogProps{
    messageList?:Array<ChatMessage>
}

var lastMsgList:Array<ChatMessage> = []

const ChatDialog:React.FC<ChatDialogProps> = (props:ChatDialogProps)=> {
    
    const textareaID = "chat-input-textarea";
    const [msgList,setMsgList] = useState<Array<ChatMessage>>(lastMsgList||[]);
    const [chatMsg,setChatMsg] = useState<string>("");
    const {state} = useLocation();
    const {userInfo} = useContext(AuthenticationContext);
    const ref = useRef<any>(null);

    useEffect(()=>{
        setupTextArea();
        getContactInfo();
        PageHelper.disableHtmlBodyScroll();
        setUpConversationsIfNeed();
        getMessageHistory(getContactInfo().userid,userInfo.userid);
        ChatHelper.setupSocket({onConnected,onError})    
        if(state.group){
            eventEmitter.subscribe(constants.str.chat.newGroupMessage,onNewMsg);
        }else{
            eventEmitter.subscribe(constants.str.chat.newMessage,onNewMsg);
        }
        return ()=>{    
            PageHelper.rollbackHtmlBodyStyle();
            if(state.group){
                eventEmitter.unsubscribe(constants.str.chat.newGroupMessage);
            }else{
                eventEmitter.unsubscribe(constants.str.chat.newMessage);
            }
            state.group && leaveGroup();
            lastMsgList = [];
        }
    },[state])

    const joinGroup = ()=>{
        if(state.group){
            ChatHelper.joinGroup(state.group.groupId,(status:any)=>{
                console.debug("haha")
            },(err:any)=>{
                console.error(err);
            })        
        }
    }

    const leaveGroup = ()=> {
        if(state.group){
            ChatHelper.leaveGroup(state.group.groupId,(res:any)=>{
                console.debug("leave group success")
            },(err:any)=>{
    
            })    
        }
    }

    const onConnected = ()=> {
        //dont know why need settimeout that user can join group success.
        setTimeout(()=>{
            joinGroup();
        },50)
    }

    const onNewMsg = (newMsg:ChatMessage)=>{
        console.debug(`got new msg: ${JSON.stringify(newMsg)}`);
        if(!state.group && newMsg.from !== getContactInfo().userid){
            return;
        }
        appendNewMsg(newMsg);
    }

    const onError = (err:any)=>{
        toast(`${err.message}`);
    }

    const getContactInfo = ()=> {
        state && 
        state.contact && 
        console.debug(`contact info ${JSON.stringify(state.contact)}`);
        return state.contact||{};
    }

    const setUpConversationsIfNeed = ()=> {
        if(state.group){
            ChatService.checkConversation({
                from:userInfo.userid,
                to:getContactInfo().userid,
                groupid: state.group.groupId||""
            }).then(()=>{
                console.debug("success")
            }).catch((err)=>{
                PopupDialog.showBsError(err);
            });    
        }
    }

    const getMessageHistory = (from:string,to:string)=> {
        if(state.group){
            ChatService.getGroupHistoryMessages({
                userId:userInfo.userid,
                groupId:state.group.groupId,
                page:msgList.length/100
            }).then((messages:Array<ChatMessage>)=>{
                appendNewMsgs(messages);
            }).catch((err)=>{
                PopupDialog.showBsError(err);
            }) 
        }else{
            ChatService.getHistoryMessages({from,to,fromName:getContactName(),page:msgList.length/100})
            .then((messages:Array<ChatMessage>)=>{
                appendNewMsgs(messages);
            }).catch((err)=>{
                PopupDialog.showBsError(err);
            })    
        }
    }

    const getContactName = ()=> {
        return getContactInfo().nickname||getContactInfo().username||"unknown"
    }

    const setupTextArea = ()=> {
        var textArea = document.getElementById(textareaID);
        if(textArea){
            textArea.setAttribute("rows","1");
            textArea.oninput = (e:Event)=>{
                textArea?.setAttribute("style",`height:auto;`);
                textArea?.setAttribute("style",`height:${textArea?.scrollHeight-10}px;`);
            }    
        }
    }

    const onChatMsgChange = (e:any)=> {
        e.preventDefault();
        var newMsg = (e.currentTarget.value||"").replaceAll(/</g,"&lt;").replaceAll(/>/g,"&gt;");
        setChatMsg(newMsg);
    }

    const sendMsg = ()=> {
        if(utils.str.isNullOrEmpty(chatMsg)){
            return;
        }

        var createTime = moment().unix().toString();
        var contact = getContactInfo();
        console.debug(`user info ${JSON.stringify(contact)}`);
        var newMsg = new ChatMessage({
            message:chatMsg,
            toUser:contact.userid,
            from:userInfo.userid||"",
            avatarUrl:userInfo.avatar||require("../../../resources/images/OIP-C.jpeg"),
            fromNickName:userInfo.nickname||"",
            messageKind:ChatMessageKind.plainText,
            createTime:createTime,
            messageSenderReceiverType:ChatMessageSenderReceiverType.sender
        });
        if(state.group){
            ChatHelper.sendGroupMsg(state.group.groupId,newMsg,(msgId?:string)=>{
                newMsg.messageId = msgId;
                appendNewMsg(newMsg);
            },(err:any)=>{
                console.debug(`got err: ${err.message}`)
                toast(err.message);
            });
        }else{
            ChatHelper.sendPrivateMsg(newMsg,(msgId?:string)=>{
                newMsg.messageId = msgId;
                appendNewMsg(newMsg);
            },(err:any)=>{
                console.debug(`got err: ${err.message}`)
                toast(err.message);
            });    
        }
    }

    const appendNewMsg = (newMsg:ChatMessage)=>{
        appendNewMsgs([newMsg]);
    }

    const appendNewMsgs = (newMsgs:Array<ChatMessage>)=>{
        var oldList = Array.from(lastMsgList);
        var newMsgList = oldList.concat(newMsgs);
        lastMsgList = newMsgList;
        // console.debug(`new msg list ${JSON.stringify(newMsgList)}`);
        setMsgList(newMsgList);
        setChatMsg("");
        scrollToLast();
        var inputArea:any = document.getElementById(textareaID)
        if(inputArea){
            //rollback input area height. this is a trick
            inputArea.style.height = 0;
        }
    }

    const scrollToLast = ()=> {
        // var chatListcontainer =  document.getElementById("listcontainer");
        setTimeout(()=>{
            var chatList =  document.getElementById("chatlist");
            var lastItems = chatList?.getElementsByTagName("li");
            var lastItem:HTMLLIElement;
            if(lastItems){
                lastItem = lastItems[lastItems.length - 1]
                chatList?.scrollTo({left:0,top:chatList?.scrollHeight})
                // chatList && chatListcontainer?.scrollTo({left:0,top:chatList?.scrollTop+chatList?.scrollHeight})
            }    
        },50)
    }

    return (<Container fluid id="chatbox"  className="d-flex flex-column m-0 p-0 root-container">
        {state.group ? <Container fluid className="d-flex flex-row justify-content-between m-0 p-1">
            <p style={{fontSize:18,verticalAlign:"center"}}>Chat in <b>{state.group.groupName}</b></p>
            <p><a className="link" onClick={(e)=>{
                e.preventDefault();
                ref && ref.current.showContactList();
            }}>Settings</a></p>
        </Container> : <Container fluid className="d-flex flex-row justify-content-between m-0 p-1">
            <p style={{fontSize:18,verticalAlign:"center"}}>Chat with &nbsp;
            <Image src={require("../../../resources/images/OIP-C.jpeg")} width={20} height={20}/>
            &nbsp;&nbsp;{getContactName()}</p>
            {state.group && <p><a className="link" onClick={(e)=>{
                e.preventDefault();
                ref && ref.current.showContactList();
            }}>Settings</a></p>}
        </Container>}
        
        {state.group && <ChatDialogContactList group={state.group} ref={ref}/>}
        <Container fluid className="d-flex message-list-container pe-1" onDrag={()=>{}}>
            <ul id="chatlist" className="message-list">
                {msgList.map((msg,idx)=>{
                    const isSender = msg.messageSenderReceiverType === ChatMessageSenderReceiverType.sender;
                    const appendix = isSender ? "row-reverse":""
                    const name = isSender ? userInfo.nickname||userInfo.username : msg.fromNickName;
                    return (<li 
                        key={`msg-key-${idx}`}>
                                <div className={`item-content ${appendix}`}>
                                    <div style={{display:"flex",flexDirection:'column',alignItems:'center'}}>
                                        <img src={msg.avatarUrl||require("../../../resources/images/OIP-C.jpeg")} style={{width:50,height:50,objectFit:"cover"}}/>
                                        <p style={{marginTop:2,fontSize:10}}>{name}</p>
                                    </div>
                                    <div className="text-bubble">
                                        <p className="msg-item-text">{`${msg.message}`}</p>
                                    </div>
                                </div>
                            </li>)
                })}
            </ul>
        </Container>
        <Container fluid key={"bottomBar"} className="m-0 mb-2 p-0 bottomBar">
            <InputGroup>
                <textarea id={`${textareaID}`} 
                    wrap="wrap" 
                    placeholder="Input message here" 
                    value={chatMsg}
                    className="messageInput"
                    onChange={onChatMsgChange}
                />
                    {/* <Form.Control as={'textarea'} rows={3} className="textinput"/> */}
                    <Button variant="primary" className="sendBtn bg-primary" 
                    onClick={sendMsg}>Send</Button>
                </InputGroup>
        </Container>
        </Container>)
}

ChatDialog.defaultProps = {
    messageList:[
    ]
}


export default ChatDialog;

